package so.sao.shop.supplier.service.authorized.impl;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.PageInfo;

import so.sao.shop.supplier.config.CommConstant;
import so.sao.shop.supplier.config.sms.SmsService;
import so.sao.shop.supplier.dao.UserDao;
import so.sao.shop.supplier.dao.authorized.*;
import so.sao.shop.supplier.domain.User;
import so.sao.shop.supplier.domain.authorized.*;
import so.sao.shop.supplier.pojo.Result;
import so.sao.shop.supplier.pojo.SystemContext;
import so.sao.shop.supplier.pojo.input.auth.AdminUserStatusInput;
import so.sao.shop.supplier.pojo.input.auth.ChildrenAccountInput;
import so.sao.shop.supplier.pojo.output.authorized.ChildrenAccountOut;
import so.sao.shop.supplier.pojo.vo.authorized.ChildrenAccountVo;
import so.sao.shop.supplier.service.authorized.ChildrenAccountService;
import so.sao.shop.supplier.util.JwtTokenUtil;
import so.sao.shop.supplier.util.PageTool;


/**
 * <p>Version: supplier V1.1.0 </p>
 * <p>Title: AuthUserServiceImpl</p>
 * <p>Description:权限设置用户Service层 </p>
 *
 * @author: taowang
 * @Date: Created in 2017/11/2 16:24
 */
@Service
public class ChildrenAccountServiceImpl implements ChildrenAccountService {

	/**
	 * 创建发送短信线程
	 */
	ExecutorService tpe = Executors.newFixedThreadPool(1);
	/**
	 * 第一次发送密码
	 */
	@Value("${shop.aliyun.sms.sms-template-code2}")
	String smsTemplateCode2;
	/**
	 * 启用账号短信通知
	 */
	@Value("${shop.aliyun.sms.sms-template-code7}")
	String smsTemplateCode7;
	/**
	 * 禁用账号短信通知
	 */
	@Value("${shop.aliyun.sms.sms-template-code8}")
	String smsTemplateCode8;
    @Autowired
    private UserDao userDao;
    @Autowired
    private ChildrenAccountDao childrenAccountDao;
    @Autowired
    private UserRolesDao userRolesDao;
    @Autowired
    private PermissionDao permissionDao;
    @Autowired
	private SmsService smsService;
	@Autowired
    private RoleDao roleDao;
	@Autowired
	private RolePermissionDao rolePermissionDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> updateChildrenAccount(ChildrenAccountVo childrenAccountVo){
        //查询修改前的用户详情
        ChildrenAccount oldChildrenAccount = childrenAccountDao.selectByPrimaryKey(childrenAccountVo.getUserId());
        //判断是否修改手机号码
        if(!oldChildrenAccount.getLoginName().equals(childrenAccountVo.getLoginName())){
            //查询修改的手机号码是否存在
            ChildrenAccountVo newChildrenAccountVo = childrenAccountDao.findUserByPhone(childrenAccountVo.getLoginName());
            if (newChildrenAccountVo != null ){
                return Result.fail("该手机号码已被注册,请更换手机号码!");
            }
        }
        //查询该用户所有的角色id
        List<Long> list = childrenAccountDao.findUserRolesByUserId(childrenAccountVo.getUserId());
        if(list != null && !list.isEmpty()){
            //删除该用户关联的角色
            childrenAccountDao.deleteUserRoles(list);
        }
        //修改用户信息
		childrenAccountVo.setUpdatedAt(new Date());
        childrenAccountDao.updateByPrimaryKeySelective(childrenAccountVo);
		List<Long> roleList  = childrenAccountVo.getRoleIds();
		if(roleList != null&&roleList.size()>0){
			//批量插入用户角色关联信息
			childrenAccountDao.saveUserRoles(childrenAccountVo.getUserId(),roleList);
		}
        return Result.success("更新成功");
    }


    @Override
	@Transactional(rollbackFor = Exception.class)
    public Result<?> updateUserStatus(AdminUserStatusInput userStatusInput){
		tpe.execute(new Runnable() {
			@Override
			public void run() {
				smsService.sendSms(Collections.singletonList(userStatusInput.getLoginName()),
					Arrays.asList("phone","password"),Arrays.asList(userStatusInput.getLoginName(),userStatusInput.getLoginName()),
						CommConstant.USER_ACTIVE_STATUS.equals(userStatusInput.getUserStatus())?smsTemplateCode7:smsTemplateCode8);
				}
		});
		userStatusInput.setUpdateAt(new Date());
		userDao.updateUserStatus(userStatusInput);
    	return Result.success("更新成功");
    }

    
    @Override
	@Transactional(rollbackFor = Exception.class)
	public Result<?> save(ChildrenAccountVo childrenAccountVo) {
		//查询修改的手机号码是否存在
		ChildrenAccountVo newChildrenAccountVo = childrenAccountDao.findUserByPhone(childrenAccountVo.getLoginName());
    	if(newChildrenAccountVo != null ) {
    		return Result.fail("当前用户已经注册,请更换手机号码!");
    	}
    	childrenAccountVo.setLoginPassword(new BCryptPasswordEncoder().encode("123456"));
    	childrenAccountVo.setCreatedAt(new Date());
    	childrenAccountVo.setUpdatedAt(new Date());
    	childrenAccountVo.setLastLoginTime(new Date());
    	childrenAccountVo.setUserStatus(CommConstant.USER_ACTIVE_STATUS);
    	//插入子账户信息
		childrenAccountDao.insert(childrenAccountVo);
		List<Long> roleIds = childrenAccountVo.getRoleIds();
		if(roleIds != null&&roleIds.size()>0){
			UserRoles userRoles = null;
			for(Long roleId:roleIds) {
				userRoles = new UserRoles();
				userRoles.setUserId(childrenAccountVo.getUserId());
				userRoles.setRoleId(roleId);
				userRoles.setCreatedAt(new Date());
				//插入角色信息
				userRolesDao.insert(userRoles);
			}
		}
		tpe.execute(new Runnable() {
			@Override
			public void run() {
				smsService.sendSms(Collections.singletonList(childrenAccountVo.getLoginName()),Arrays.asList("phone","password"), Arrays.asList(childrenAccountVo.getLoginName(),"123456"), smsTemplateCode2);
			}
		});
		return Result.success("添加成功");
	}
    
    @Override
	public Result<?> list(ChildrenAccountInput childrenAccountInput) {
		PageTool.startPage(childrenAccountInput.getPageNum(), childrenAccountInput.getPageSize());
		//查询符合条件的结果
		List<ChildrenAccount> users = childrenAccountDao.findAll(childrenAccountInput);
		PageInfo<ChildrenAccount> pageInfo = new PageInfo<ChildrenAccount>(users);
		return Result.success("查询成功!", pageInfo);
	}

	@Override
	public Result<?> selectChildrenAccountDetails( Long updateUserId){
		//查询修改前的用户详情放入返回对象中
		ChildrenAccount childrenAccount = childrenAccountDao.selectByPrimaryKey(updateUserId);
		if(childrenAccount == null){
			return Result.fail("用户不存在！");
		}
		ChildrenAccountOut childrenAccountOut = new ChildrenAccountOut();
		childrenAccountOut.setLoginName(childrenAccount.getLoginName());
		childrenAccountOut.setUserId(childrenAccount.getUserId());
		childrenAccountOut.setUserName(childrenAccount.getUserName());
		childrenAccountOut.setUserStatus(childrenAccount.getUserStatus());
		//查询该用户拥有的角色放入返回对象中
		childrenAccountOut.setRoleId(childrenAccountDao.findRolesByUserId(updateUserId));
		//查询该用户拥有的权限放入返回对象中
		Long type = null;
		List<Permission> list = permissionDao.findMenuPermission(updateUserId,type,null);
		//取出权限字段，重新封装list
		List<Long> newList = new ArrayList<>();
		for (Permission permission :list){
			newList.add(permission.getId());
		}
		childrenAccountOut.setPerId(newList);
		return Result.success("查询成功",childrenAccountOut);
	}

	@Override
	public Result<?> updatePassword(ChildrenAccountVo childrenAccountVo){
		ChildrenAccount oldChildrenAccount = childrenAccountDao.selectByPrimaryKey(childrenAccountVo.getUserId());
		if (oldChildrenAccount == null ){
			return Result.fail("用户数据有误");
		}
		if(new BCryptPasswordEncoder().matches(childrenAccountVo.getLoginPassword(),oldChildrenAccount.getLoginPassword())){
			return Result.fail("新密码不能和旧密码相同");
		}
		userDao.updatePassword(childrenAccountVo.getUserId(),new BCryptPasswordEncoder().encode(childrenAccountVo.getLoginPassword()), new Date());
		tpe.execute(new Runnable() {
			@Override
			public void run() {
				smsService.sendSms(Collections.singletonList(childrenAccountVo.getLoginName()),Arrays.asList("phone","password"), Arrays.asList(childrenAccountVo.getLoginName(),childrenAccountVo.getLoginPassword()), smsTemplateCode2);
			}
		});
		return Result.success("修改密码成功");
	}

	/**
	 * 创建供应商时初始化供应商管理员角色公共方法
	 * @param userId
	 */
	@Transactional(rollbackFor = Exception.class)
	public void createAccountAdmin(Long userId){
		//获取当前登录用户信息
		User user = JwtTokenUtil.getCurrentUser();
		//查询角色表中有无初始化供应商超级管理员角色
		Role role = roleDao.findByRoleName(CommConstant.SUPPLIER_ROLE,null);
		//查询供应商超级管理员具备的权限
		List<Long> newList = permissionDao.findAccountTree();
		UserRoles userRoles = null;
		if (role == null){
			userRoles = this.fullUpdate(user,newList);
		}else {
			userRoles = this.portionUpdate(role,newList);
		}
		//将该角色关联要创建的供应商用户
		userRoles.setUserId(userId);
		userRoles.setCreatedAt(new Date());
		userRoles.setUpdatedAt(new Date());
		userRolesDao.insert(userRoles);
	}

	/**
	 * 项目初始化做全量更新供应商权限
	 * @param user
	 * @param newList
	 */
	private UserRoles fullUpdate(User user,List<Long> newList) {
		UserRoles userRoles = new UserRoles();
		//创建该角色
		Role role = new Role();
		role.setName(CommConstant.SUPPLIER_ROLE);
		role.setIsAdmin(CommConstant.IS_NOT_ADMIN);
		role.setOperatorId(user.getId());
		roleDao.save(role);
		//插入角色权限关联数据
		createRolePermission(role.getId(),newList);
		userRoles.setRoleId(role.getId());
		return userRoles;
	}

	/**
	 *	增量更新供应商角色权限
	 * @param role
	 * @param newList
	 */
	private UserRoles portionUpdate(Role role,List<Long> newList) {
		UserRoles userRoles = new UserRoles();
		userRoles.setRoleId(role.getId());
		//根据角色id查询该角色关联的数据
		List<RolePermission> oldList = rolePermissionDao.selectByRoleId(role.getId());
		if(oldList == null ||oldList.isEmpty()){
			//插入角色权限关联数据
			createRolePermission(role.getId(),newList);
			return userRoles;
		}
		List<Long> pids = new ArrayList<>();
		List<Long> pidss = new ArrayList<>();
		for(RolePermission rp:oldList){
			pids.add(rp.getPermissionId());
			pidss.add(rp.getPermissionId());
		}
		pids.removeAll(newList);
		newList.removeAll(pidss);
		if(!pids.isEmpty()) {
			//删除无用的关联数据
			for(Long old : pids) {
				rolePermissionDao.deleteRolePer(role.getId(),old);
			}
		}
		if(!newList.isEmpty()){
			//插入新增的角色权限关联数据
			createRolePermission(role.getId(),newList);
		}
		return userRoles;
	}
	/**
	 * 批量插入角色权限关联数据
	 */
	public void createRolePermission(Long roleId ,List<Long> inPutList){
		List<RolePermission> list = new ArrayList<>();
		RolePermission rolePermission = null;
		for (Long pid :inPutList) {
			rolePermission = new RolePermission();
			rolePermission.setRoleId(roleId);
			rolePermission.setPermissionId(pid);
			list.add(rolePermission);
		}
		//批量插入角色权限关联数据
		rolePermissionDao.save(list);
	}

}